home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue43 / tooltips / DBHntGrd.pas next >
Encoding:
Pascal/Delphi Source File  |  1999-01-25  |  5.5 KB  |  206 lines

  1. unit DBHntGrd;
  2. {$ifdef Ver80} { Delphi 1.0x }
  3.   {$define DelphiLessThan3}
  4. {$endif}
  5. {$ifdef Ver90} { Delphi 2.0x }
  6.   {$define DelphiLessThan3}
  7. {$endif}
  8. {$ifdef Ver93} { C++ Builder 1.0x }
  9.   {$define DelphiLessThan3}
  10. {$endif}
  11.  
  12. interface
  13.  
  14. uses
  15.   WinProcs, WinTypes, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  16.   Dialogs, Grids, DBGrids;
  17.  
  18. type
  19.   THintDBGrid = class(TDBGrid)
  20.   private
  21.     FHintWnd: THintWindow;
  22.   protected
  23.     function CalcHintRect(MaxWidth: Integer;
  24.       const AHint: string; HintWnd: THintWindow): TRect;
  25.     procedure DoHint(X, Y: Integer);
  26.   public
  27.     procedure CMMouseEnter(var Msg: TMessage); message cm_MouseEnter;
  28.     procedure CMMouseLeave(var Msg: TMessage); message cm_MouseLeave;
  29.     procedure WMMouseMove(var Msg: TWMMouseMove); message wm_MouseMove;
  30.   end;
  31.  
  32. {$ifdef DelphiLessThan3}
  33.   { The hint window in Delphi 1 and 2 would beep if you clicked it }
  34.   { These modifications fix that }
  35.   TCustomHint = class(THintWindow)
  36.   private
  37.     procedure WMNCHitTest(var Msg: TWMNCHitTest);
  38.       message wm_NCHitTest;
  39.   protected
  40.     procedure CreateParams(var Params: TCreateParams); override;
  41.   end;
  42.  
  43. { The private routine Forms.ForegroundTask was only made }
  44. { available in Delphi 3. This is a cheap'n'nasty version of it }
  45. function ForegroundTask: Boolean;
  46. {$endif}
  47.  
  48. procedure Register;
  49.  
  50. implementation
  51.  
  52. procedure Register;
  53. begin
  54.   RegisterComponents('Clinic', [THintDBGrid]);
  55. end;
  56.  
  57. {$ifdef DelphiLessThan3}
  58. { The private routine Forms.ForegroundTask was only made }
  59. { available in Delphi 3. This is a cheap'n'nasty version of it }
  60. function ForegroundTask: Boolean;
  61. begin
  62.   Result := FindControl(GetActiveWindow) <> nil
  63. end;
  64. {$endif}
  65.  
  66. { THintStringGrid }
  67.  
  68. function THintDBGrid.CalcHintRect(MaxWidth: Integer;
  69.   const AHint: string; HintWnd: THintWindow): TRect;
  70. {$ifdef DelphiLessThan3}
  71. var
  72.   Buf: array[0..511] of Char;
  73. begin
  74.   Result := Rect(0, 0, MaxWidth, 0);
  75.   { Ask Windows to do the hard calculation work }
  76.   DrawText(HintWnd.Canvas.Handle, StrPCopy(Buf, AHint), -1, Result,
  77.     DT_CALCRECT or DT_LEFT or DT_WORDBREAK or DT_NOPREFIX);
  78.   { Add some breathing room }
  79.   Inc(Result.Right, 6);
  80.   Inc(Result.Bottom, 2);
  81. {$else}
  82. begin
  83.   { Delphi 3+ makes this method available }
  84.   Result := HintWnd.CalcHintRect(Screen.Width, AHint, nil)
  85. {$endif}
  86. end;
  87.  
  88. procedure THintDBGrid.CMMouseEnter(var Msg: TMessage);
  89. var
  90.   Pt: TPoint;
  91. begin
  92.   GetCursorPos(Pt);
  93.   Pt := ScreenToClient(Pt);
  94.   DoHint(Pt.X, Pt.Y)
  95. end;
  96.  
  97. procedure THintDBGrid.CMMouseLeave(var Msg: TMessage);
  98. begin
  99.   inherited;
  100.   { Could destroy it, but this takes less time }
  101.   if Assigned(FHintWnd) then
  102.     FHintWnd.ReleaseHandle;
  103. end;
  104.  
  105. procedure THintDBGrid.DoHint(X, Y: Integer);
  106. const
  107.   TextOffset = 2;
  108. var
  109.   Col, Row, LogCol, LogRow: Longint;
  110.   R, OldR: TRect;
  111.   Pt: TPoint;
  112.   GPt: TGridCoord;
  113.   OldActive: Integer;
  114.   Text: String;
  115. begin
  116.   { Check cell under mouse }
  117.   GPt := MouseCoord(X, Y);
  118.   Col := GPt.X;
  119.   Row := GPt.Y;
  120.   LogCol := Col;
  121.   LogRow := Row;
  122.   { Title row needs to be taken account of }
  123.   if dgTitles in Options then Dec(LogRow);
  124.   { Indicator column needs to be taken account of }
  125.   if dgIndicator in Options then Dec(LogCol);
  126.   Text := '';
  127.   if (LogCol >= 0) and (LogRow >= 0) then
  128.   begin
  129.     OldActive := DataLink.ActiveRecord;
  130.     try
  131.       Datalink.ActiveRecord := LogRow;
  132.     {$ifdef Win32}
  133.       Text := Columns[LogCol].Field.DisplayText
  134.     {$else}
  135.       Text := Fields[LogCol].DisplayText
  136.     {$endif}
  137.     finally
  138.       Datalink.ActiveRecord := OldActive
  139.     end
  140.   end;
  141.   { If it is a cell, and in-place editor not present, }
  142.   { and text is bigger than screen space, and not at design-time }
  143.   Canvas.Font := Font;
  144.   if (Text <> '') and not EditorMode and ForegroundTask and
  145.      (Canvas.TextWidth(Text) + TextOffset > ColWidths[Col]) and
  146.      not (csDesigning in ComponentState) then
  147.   begin
  148.     { Make sure hint window exists }
  149.     if not Assigned(FHintWnd) then
  150.     begin
  151.       FHintWnd := HintWindowClass.Create(Self);
  152.       FHintWnd.Color := Application.HintColor;
  153.     end;
  154.     { Set hint text }
  155.     Hint := Text;
  156.     { Calculate rect size }
  157.     R := CalcHintRect(Screen.Width, Hint, FHintWnd);
  158.     { Find target location }
  159.     Pt := ClientToScreen(CellRect(Col, Row).TopLeft);
  160.     { Tweak position so it is the same as the grid cell (hopefully) }
  161.   {$ifdef DelphiLessThan3}
  162.     Inc(Pt.Y);
  163.   {$else}
  164.     Dec(Pt.X);
  165.     Dec(Pt.Y);
  166.   {$endif}
  167.     OffsetRect(R, Pt.X, Pt.Y);
  168.     { Only draw it if it has moved - compare top-left }
  169.     { (could compare whole rect but the hint sometimes grows itself) }
  170.     GetWindowRect(FHintWnd.Handle, OldR);
  171.     if not IsWindowVisible(FHintWnd.Handle) or
  172.        not ((R.Left = OldR.Left) and (R.Top = OldR.Top)) then
  173.       FHintWnd.ActivateHint(R, Hint)
  174.   end
  175.   else
  176.     if Assigned(FHintWnd) then
  177.       FHintWnd.ReleaseHandle
  178. end;
  179.  
  180. procedure THintDBGrid.WMMouseMove(var Msg: TWMMouseMove);
  181. begin
  182.   inherited;
  183.   DoHint(Msg.XPos, Msg.YPos)
  184. end;
  185.  
  186. {$ifdef DelphiLessThan3}
  187. { TCustomHint }
  188.  
  189. procedure TCustomHint.CreateParams(var Params: TCreateParams);
  190. begin
  191.   inherited CreateParams(Params);
  192.   Params.Style := Params.Style and not ws_Disabled;
  193. end;
  194.  
  195. procedure TCustomHint.WMNCHitTest(var Msg: TWMNCHitTest);
  196. begin
  197.   Msg.Result := HTTRANSPARENT;
  198. end;
  199.  
  200. initialization
  201.   Application.ShowHint := not Application.ShowHint;
  202.   HintWindowClass := TCustomHint;
  203.   Application.ShowHint := not Application.ShowHint;
  204. {$endif}
  205. end.
  206.